Using View Groups
This section demonstrates how to use QuickDraw GX view groups. It shows how you can
- create and manipulate view group objects
- set up an offscreen drawing environment
- measure a shape in a view group
Creating and Manipulating View Group Objects
QuickDraw GX provides theGXNewViewGroup
function to allow you to create a new view group object, and theGXDisposeViewGroup
function to delete it. Normally, you create a view group only for the purpose of offscreen drawing.Listing 7-13 is a continuation of the routine in Listing 7-12 on page 7-58 that sets up a data structure for offscreen drawing through a given view port. This part of the code fills in various fields of the
buffers
data structure and callsGXNewViewGroup
to create an offscreen view group. In addition, it callsGXNewViewPort
to create an offscreen view port (slavePort
) in the new group, andGXGetShapeGlobalViewDevices
to copy all drawable devices from the original onscreen view port (port
) into a list in the data structure.Listing 7-13 Setting up a data structure for offscreen drawing
. . /* continued from Listing 7-12 on page 7-58 */ . buffersHandle = (viewPortBuffer) NewHandle(sizeof (viewPortBufferRecord) + (deviceCount - 1) * sizeof(gxViewDevice)); NilParamReturnNil(port); /* error-check the handle */ HLock((Handle) buffersHandle); buffers = *buffersHandle; buffers->group = GXNewViewGroup(); buffers->masterPort = port; buffers->slavePort = GXNewViewPort(buffers->group); buffers->area = area; buffers->draw = GXNewShape(gxPictureType); buffers->deviceCount = deviceCount; GXSetViewPortDither(buffers->slavePort, GXGetViewPortDither(port)); GXGetShapeGlobalViewDevices(area, port, buffers->devices);Once you have created a view group object, you can assign view ports and view
devices to it with theGXSetViewPortViewGroup
function (as described under "Manipulating View Port Object Properties" beginning on page 7-42) and theGXSetViewDeviceViewGroup
function (as described under "Manipulating View Device Object Properties" beginning on page 7-54).At any time, you can retrieve a list of view ports or view devices that belong
to a view group by calling the functionsGXGetViewGroupViewPorts
andGXGetViewGroupViewDevices
. See Listing 7-2 on page 7-44 for an example of the
use ofGXGetViewGroupViewPorts
; see Listing 7-10 on page 7-54 for an example of the use ofGXGetViewGroupViewDevices
.When you have finished using an offscreen view group, you delete it with the
GXDisposeViewGroup
function. For an example of the use ofGXDisposeViewGroup
, see page 7-63.The
GXNewViewGroup
function is described on page 7-122. TheGXDisposeViewGroup
function is described on page 7-122.The
GXGetViewGroupViewPorts
function is described on page 7-123. TheGXGetViewGroupViewDevices
function is described on page 7-124.Setting Up an Offscreen View Group
This section shows how to set up a view port for offscreen drawing. Examples of most of the steps shown here have already been presented elsewhere in this chapter, although not all together.Offscreen drawing requires creating a new view group, so that drawing does not conflict with the screen devices view group. You must also create a view port to draw into. To set up the view port, you must create a view device object; however, for offscreen drawing the view device object need not correspond to any physical device. Follow this typical sequence of steps to set up an offscreen view group:
Listing 7-14 is a partial example of a routine that sets up an offscreen drawing environment. It does not show how the bitmap shape (
- Create a new view group.
- Create a new view device in this view group, specifying a bit map that represents the area that you may want to copy onscreen later.
- Create a new view port in this view group.
- Retrieve the bitmap as a shape object of its own, so that you can later draw it directly onscreen.
- Create a transform object for your shapes, and assign the view port to its view port list.
bitShape
) for the device is set up. See the bitmap shapes chapter of Inside Macintosh: QuickDraw GX Graphics for information on bitmap shapes.Listing 7-14 Setting up a view port and view group for offscreen drawing
gxShape myDraw, bitShape; gxTransform myXform; gxViewDevice myDevice; gxViewPort myPort; gxViewGroup myGroup; . . /* set up bitmap shape for offscreen view device */ . myGroup = GXNewViewGroup(); myDevice = GXNewViewDevice(myGroup, bitShape); myPort = GXNewViewPort(myGroup); myDraw = GXGetViewDeviceBitmap(myDevice); myXform = GXNewTransform(); GXSetTransformViewPorts(myXform, 1, &myPort);ThemyDraw
shape represents your offscreen drawing buffer. Whenever you draw a shape that hasmyXform
as its transform object, drawing takes place offscreen, in the pixel image associated withmyDraw
. If you added a view port in the onscreen view group to the view port list ofmyXform
, drawing could take place both offscreen and onscreen simultaneously.It is useful to have a direct reference to
myDraw
because you can draw it itself, which would have the effect of transferring the offscreen buffer onto the screen (ifmyDraw
references a transform object that references onscreen view ports).When you are finished with offscreen drawing, you can dispose of the objects you have created:
GXDisposeShape(myDraw); GXDisposeTransform(myXform); GXDisposeViewGroup(myGroup);You do not have to explicitly dispose of your offscreen view port or view device, because callingGXDisposeViewGroup
causes QuickDraw GX to dispose of all of its view ports and view devices.Measuring a Shape in Global Space
TheGXGetShapeGlobalBounds
function measures the bounding rectangle of a shape in global coordinates--that is, after the transform mapping has been applied to the shape geometry, and after all view port mappings have been applied. You can thus useGXGetShapeGlobalBounds
to compare the true positions and sizes of any two shapes in the same view group, even if they do not share the same view port or do not appear on the same view device. (To compare the positions and sizes of two shapes in the same view port, you can use theGXGetShapeLocalBounds
function; to measure a shape on a view device, useGXGetShapeDeviceBounds
.)Listing 7-15 is a library function used in offscreen drawing. The function returns the device characteristics (a bitmap structure plus an offset) of a particular "area," the intersection of an offscreen view device and an offscreen view port. Area-characteristics structures are used by this library to store device-specific drawing information for each area within the offscreen view port occupied by the pixel image of a device. This listing uses
GXGetShapeGlobalBounds
to determine the intersection of the specified shape (area
) with the specified view device (device
), which determines the size of the image stored in the area-characteristics structure (x
).Listing 7-15 Returning the characteristics of an offscreen device area
static areaCharacteristics GetAreaCharacteristics(gxShape area, gxViewDevice device, gxViewPort port) { areaCharacteristics x; /* a bitmap structure & location */ gxRectangle bounds; gxShape bitShape; gxMapping map; . . . /* get device bitmap and shape bounds on device */ bitShape = GXGetViewDeviceBitmap(device); GXGetShapeGlobalBounds(area, port, nil, &bounds); /* fill out the area-characteristics structure */ GXGetBitmap(bitShape, &x.bits, nil); if (x.bits.space == gxIndexedSpace) GXCloneColorSet(x.bits.set); if (x.bits.profile) GXCloneColorProfile(x.bits.profile); GXDisposeShape(bitShape); x.offset.x = bounds.left; x.offset.y = bounds.top; x.bits.width = FixedRound(bounds.right) - FixedRound(bounds.left); x.bits.height = FixedRound(bounds.bottom) - FixedRound(bounds.top); /* map the area offset back to local space, store in x */ InvertMapping(&map, GXGetViewPortGlobalMapping(port, &map)); MapPoints(&map, 1, &x.offset); return x; }TheGXGetShapeGlobalBounds
function is described on page 7-125.The
GXGetShapeLocalBounds
function is described on page 7-96. TheGXGetShapeDeviceBounds
function is described on page 7-116.